/**
 *用以太网线缆将 n 台计算机连接成一个网络，计算机的编号从 0 到 n-1。线缆用 connections 表示，其中 connections[i] = [a, b] 连接了计算机 a 和 b。
 *
 * 网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其他任意一台计算机。
 *
 * 给你这个计算机网络的初始布线 connections，你可以拔开任意两台直连计算机之间的线缆，并用它连接一对未直连的计算机。请你计算并返回使所有计算机都连通所需的最少操作次数。如果不可能，则返回 -1 。
 *https://leetcode.cn/problems/number-of-operations-to-make-network-connected/description/
 */
class MakeConnected {
    public int makeConnected(int n, int[][] connections) {
        int len = connections.length;
        if(len + 1 < n) {
            return -1;
        }
        UnionFindSet u = new UnionFindSet(n);
        for(int[] arr : connections) {
            u.union(arr[0],arr[1]);
        }
        return  u.getCount()-1;
    }
}

class UnionFindSet
{
    private int[] elem;

    public int notSet() {
        int count = 0;
        for(int i = 0;i<this.elem.length;i++) {
            if(elem[i] == -1) {
                count++;
            }
        }
        return count;
    }
   
    public UnionFindSet(int n) {
        this.elem = new int[n];
        Arrays.fill(this.elem,-1);
       
    }

    public int findRoot(int x) {
        if(x < 0) {
            //没有这个并查集
            return -1;
        }

        while(elem[x] >= 0) {
            x = elem[x];
        }

        return x;
    }
    //将y合并到x
    public boolean union(int x,int y) {
        int x1 = findRoot(x);
        int x2 = findRoot(y);
        if(x1 == x2) {
            return true;
        }
        this.elem[x1] = this.elem[x1] + this.elem[x2];
        this.elem[x2] = x1;
        return true;

    }

    public boolean isSame(int x,int y) {
        int x1 = findRoot(x);
        int x2 = findRoot(y);
        return x1 == x2;
    }

    public int getCount() {
        int count = 0;
        for(int i = 0;i<this.elem.length;i++) {
            if(elem[i] < 0) {
                count++;
            }
        }
        return count;
    }
    
}